package com.qingmeng.outsourcing.portal.service.impl;

import com.aliyuncs.exceptions.ClientException;
import com.qingmeng.outsourcing.mapper.BalanceMapper;
import com.qingmeng.outsourcing.mapper.CheakMapper;
import com.qingmeng.outsourcing.mapper.UserMapper;
import com.qingmeng.outsourcing.model.*;
import com.qingmeng.outsourcing.portal.enums.RegisterResult;
import com.qingmeng.outsourcing.portal.enums.SMSResult;
import com.qingmeng.outsourcing.portal.enums.SMSType;
import com.qingmeng.outsourcing.portal.model.dto.UserRegisterParam;
import com.qingmeng.outsourcing.portal.service.UserService;
import com.qingmeng.outsourcing.portal.util.SecurityUtils;
import com.qingmeng.outsourcing.portal.util.ShortMessageUtil;
import com.qingmeng.outsourcing.security.util.JwtTokenUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CheakMapper Cheakmapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private BalanceMapper balanceMapper;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    /**
     * 根据用户名查询数据库中的用户
     *
     * @param username 用户名
     * @return 如果在数据库中存在，返回该用户对象；如果用户不存在返回null
     */
    @Override
    public User getUserByUsername(String username) {
        UserExample example = new UserExample();
        example.createCriteria().andUserNameEqualTo(username);
        List<User> userList = userMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(userList)) {
            return userList.get(0);
        }
        return null;
    }

    /**
     * 发送短信验证码
     *
     * @param phone    电话号码
     * @param identify 身份或功能标识 （0-为修改手机号时，1-为注册时雇主身份，2-为注册时开发者，3-为忘记密码）
     * @return 短信发送结果枚举
     */
    @Override
    public SMSResult sendMessageCode(String phone, Integer identify) {
        // 验证手机号
        if (phone == null || phone.length() != 11) {
            return SMSResult.PHONE_ERROR;
        }

        // 不是修改手机号和忘记密码（注册雇主和开发者的时候执行的分支）
        if (identify != SMSType.MODIFY_PHONE.getCode() && identify != SMSType.FORGET_PASSWORD.getCode()) {
            UserExample example = new UserExample();
            //
            example.createCriteria().andPhoneEqualTo(phone).andIsPublisherEqualTo(identify);
            if (userMapper.countByExample(example) > 0) {
                return SMSResult.PHONE_ALREADY_REGISTERED;
            }
        } else if (identify == SMSType.MODIFY_PHONE.getCode()) { // 修改手机号执行的分支
            User currentUser = SecurityUtils.getCurrentUser();
            if (currentUser == null) {
                return SMSResult.NO_LOGIN_NO_MODIFY_PHONE;
            }
            UserExample example = new UserExample();
            example.createCriteria().andPhoneEqualTo(phone);
            List<User> userList = userMapper.selectByExample(example);
            if (!CollectionUtils.isEmpty(userList)) {
                for (User user : userList) {
                    if (currentUser.getIsPublisher().equals(user.getIsPublisher())) {
                        return SMSResult.PHONE_ALREADY_REGISTERED;
                    }
                }
            }
        }
        // 生成6位随机数
        String random = ShortMessageUtil.createRandomNum(6);
        // 验证码存入数据库
        Cheak cheak =new Cheak();
        cheak.setCode(random);
        cheak.setPhone(phone);
        // 向数据库中插入生成的验证码数据
        if (Cheakmapper.insertSelective(cheak)>0) {
            try {
                // 调用工具类发送验证码
                String ret = ShortMessageUtil.sendMsg(phone, "青盟科技", "SMS_174891011", random);
                if ("网络问题，请重试".equals(ret)) {
                    return SMSResult.NETWORK_ERROR;
                } else if ("生成验证码失败".equals(ret)) {
                    return SMSResult.SEND_SMS_FAILED;
                }
            } catch (ClientException e) {
                logger.error("发送短信出现异常，异常信息为：{}", e.toString());
                return SMSResult.NETWORK_ERROR;
            }
        }

        return SMSResult.SEND_SMS_SUCCESS;
    }

    /**
     * 用户注册
     *
     * @param param 注册参数
     * @return 注册结果枚举
     */
    @Override
    public RegisterResult register(UserRegisterParam param) {
        //先检查验证码
      if (!verifyAuthCode(param.getCode(), param.getPhone())) {
           return RegisterResult.AUTH_CODE_ERROR;
       }
      //检查用户名是否重复，如果重复，直接返回
        UserExample usernameExample = new UserExample();
        usernameExample.createCriteria().andUserNameEqualTo(param.getUsername());
        if (userMapper.countByExample(usernameExample) > 0) {
            return RegisterResult.USERNAME_EXIST;
        }
       //判断当前手机号是否注册过身份
        UserExample phoneExample = new UserExample();
        phoneExample.createCriteria().andPhoneEqualTo(param.getPhone()).andIsPublisherEqualTo(param.getIdentity());
        if (userMapper.countByExample(phoneExample) > 0) {
            return RegisterResult.REG_DUPLICATED;
        }
        User user=new User();
        user.setUserName(param.getUsername());
        user.setIsPublisher(param.getIdentity());
        user.setPassword(passwordEncoder.encode(param.getPassword()));
        if (userMapper.insertSelective(user)>0) {
            Balance balance = new Balance();
            balance.setBalance(new BigDecimal("0.00"));
            balance.setUserId(user.getId());
            if (balanceMapper.insertSelective(balance) > 0) {
                return RegisterResult.REG_SUCCESS;
            }
        }
        return RegisterResult.REG_FAILED;
    }

    /**
     * 登陆
     *
     * @param username 用户名
     * @param password 密码
     * @return 包含token等信息的Map
     */
    @Override
    public Map<String, String> login(String username, String password) {
        // 使用 username 和 password 构造一个 UsernamePasswordAuthenticationToken 对象
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
        Authentication authenticate = null;
        try {
            // 验证用户名和密码
            authenticate = authenticationManager.authenticate(token);
        } catch (AuthenticationException e) {
            logger.error("用户名或密码错误：{}", e.toString());
            return null;
        }
        // 将authenticate添加到安全框架的上下文中
        SecurityContextHolder.getContext().setAuthentication(authenticate);

        // 定义返回给前端的Map
        Map<String, String> tokenMap = new HashMap<>();
        if (authenticate != null) {
            // 从验证结果返回的authenticate中获取UserDetails对象
            UserDetails userDetails = (UserDetails) authenticate.getPrincipal();
            // 根据UserDetails对象生成token字符串
            String tokenString = jwtTokenUtil.generateToken(userDetails);
            tokenMap.put("token", tokenString);
            tokenMap.put("tokenHead", jwtTokenUtil.getTokenHead());
            tokenMap.put("tokenHeader", jwtTokenUtil.getTokenHeader());
        }
        return tokenMap;
    }

    /**
     * 退出登录
     *//*
    @Override
    public void logout() {
        // 把当前用户设置成认证未通过状态
        SecurityContextHolder.getContext().getAuthentication().setAuthenticated(false);
    }
*/

    /**
     * 忘记密码的时候重置密码
     *
     * @param param 前端传递到后端的参数
     * @return 枚举
     */
   /* @Override
    public ResetPasswordResult resetPassword(ResetPasswordParam param) {
        // 验证传入的参数是否合法
        if (param == null
                || !StringUtils.hasLength(param.getPhone())
                || !StringUtils.hasLength(param.getCode())
                || !StringUtils.hasLength(param.getNewPassword())) {
            return ResetPasswordResult.INVALID_PARAM;
        }

        // 检查验证码
        if (!verifyAuthCode(param.getCode(), param.getPhone())) {
            return ResetPasswordResult.SMS_CODE_ERROR;
        }

        // 根据用户身份和电话号码查询用户
        UserExample example = new UserExample();
        example.createCriteria().andIsPublisherEqualTo(param.getIsPublisher()).andPhoneEqualTo(param.getPhone());
        List<User> userList = userMapper.selectByExample(example);
        // 数据库中查询出的用户信息
        User userInDB = null;
        if (!CollectionUtils.isEmpty(userList)) {
            userInDB = userList.get(0);
        }
        if (userInDB == null) {
            return ResetPasswordResult.PHONE_ERROR;
        }
        // 构造一个新的用户，只设置id和密码字段
        User user = new User();
        user.setId(userInDB.getId());
        user.setPassword(passwordEncoder.encode(param.getNewPassword()));
        // 将新的用户密码更新到数据库中
        if (userMapper.updateByPrimaryKeySelective(user) > 0) {
            return ResetPasswordResult.SUCCESS;
        }

        return ResetPasswordResult.FAILED;
    }*/
    /**
     * 对前端输入的验证码进行校验
     *
     * @param code  前方传递过来的验证码
     * @param phone 手机号
     * @return 校验通过返回true, 否则返回false
     */
    private boolean verifyAuthCode(String code, String phone) {
        // 判断传入的验证码是否为空
        if (!StringUtils.hasLength(code)) {
            return false;
        }
      CheakExample example = new CheakExample();
        example.createCriteria().andPhoneEqualTo(phone).andCodeEqualTo(code);
        return Cheakmapper.countByExample(example) > 0;
    }

}
